#include <opencv2/opencv.hpp>
#include <iostream>

__global__ void addKernel(int* c, const int* a, const int* b, int size) {
    int i = threadIdx.x;
    if (i < size) {
        c[i] = a[i] + b[i];
    }
}

int main() {
    // OpenCV part: Read an image
    cv::Mat image = cv::imread("input.jpg", cv::IMREAD_COLOR);
    if(image.empty()) {
        std::cerr << "Could not read the image" << std::endl;
        return 1;
    }

    // Convert the image to grayscale
    cv::Mat grayImg;
    cv::cvtColor(image, grayImg, cv::COLOR_BGR2GRAY);

    // Save the grayscale image
    cv::imwrite("output.jpg", grayImg);

    // Display the original and grayscale images
    cv::imshow("Original Image", image);
    cv::imshow("Grayscale Image", grayImg);
    cv::waitKey(0);

    // CUDA part: Simple addition of arrays
    const int arraySize = 5;
    const int a[arraySize] = {1, 2, 3, 4, 5};
    const int b[arraySize] = {10, 20, 30, 40, 50};
    int c[arraySize] = {0};

    int *dev_a, *dev_b, *dev_c;
    cudaMalloc((void**)&dev_a, arraySize * sizeof(int));
    cudaMalloc((void**)&dev_b, arraySize * sizeof(int));
    cudaMalloc((void**)&dev_c, arraySize * sizeof(int));

    cudaMemcpy(dev_a, a, arraySize * sizeof(int), cudaMemcpyHostToDevice);
    cudaMemcpy(dev_b, b, arraySize * sizeof(int), cudaMemcpyHostToDevice);

    addKernel<<<1, arraySize>>>(dev_c, dev_a, dev_b, arraySize);

    cudaMemcpy(c, dev_c, arraySize * sizeof(int), cudaMemcpyDeviceToHost);

    std::cout << "Result: ";
    for(int i = 0; i < arraySize; ++i) {
        std::cout << c[i] << " ";
    }
    std::cout << std::endl;

    cudaFree(dev_a);
    cudaFree(dev_b);
    cudaFree(dev_c);

    return 0;
}
